#coding:utf-8
from django.shortcuts import render,redirect,get_object_or_404,HttpResponse
from django.views.generic import View,DetailView,ListView
from django.views.generic.edit import CreateView,DeleteView,UpdateView
from django.http import Http404,JsonResponse
from django.core.paginator import Paginator
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.urls import reverse,reverse_lazy
from django.http import HttpResponseRedirect
from datetime import datetime
import logging
from .models import Article,Category,Tag,Link,Comment
from AppLogin.models import Users
from .forms import ArticleForm,CategoryForm,TagForm
# Create your views here.
'''通过继承Django的通用试图ListView,DetaiView,CreateView,UpdateView,FormView,DeleteView,
重写get_queryset，get_object，get_context_data等方法使代码更加简洁，灵活比如ListView的get_queryset
方法默认为返回model.objects.all(),通过重写它就可以返回自己想要的queryset，如只有作者自己的文章
'''

class ArticleListView(ListView):
    model = Article
    paginate_by = 5 #在类试图中通过paginate_by属性开启分页功能
    template_name = 'blog/index.html'
    context_object_name = 'articles'
    def get_queryset(self):
        return Article.objects.filter(status='p').order_by('-pub_date')
    #ListView默认返回model列表，通过重写get_context_data方法就可以返回自己想要的context。
    def get_context_data(self, *args, **kwargs):
        context = super(ArticleListView,self).get_context_data(**kwargs)
        context['category_list'] = Category.objects.all()[:10]
        context['hot_article_list'] = Article.objects.order_by("-views")[:10]
        context['hot_user_list'] = Users.objects.order_by("au")[:8]
        context['new_comment_list'] = Comment.objects.order_by("-create_time")[:10]
        context['link_list'] = Link.objects.order_by('-create_time')
        return context

#login_required装饰函数只能用于函数试图，使用method_decorator方法可以让login_required用于基于类的试图
#name可以是'dispatch','get','post'等方法
@method_decorator(login_required, name='dispatch')
class ArticleCreateView(CreateView):
    model = Article
    form_class = ArticleForm
    template_name = 'blog/article_create_form.html'
    context_object_name = 'form'
    #success_url = reverse_lazy('blog:blog_index')
    def form_valid(self,form):
        form.instance.author = self.request.user
        self.request.user.set_topic_num() #更新文章数
        return super().form_valid(form)

@method_decorator(login_required, name='dispatch')
class ArticleDetailView(DetailView):
    model = Article
    template_name = "blog/article_detail.html"
    context_object_name = 'article'
    #pk_url_kwarg = 'article_id'

    def get_object(self,queryset=None):
        obj = super().get_object(queryset=queryset)
        obj.viewed()
        return obj

    def get_context_data(self, **kwargs):
        article_id = self.kwargs.get('pk', '')
        kwargs['comment_list'] = Comment.objects.filter(article_id=article_id).all()
        return super(ArticleDetailView, self).get_context_data(**kwargs)

@method_decorator(login_required, name='dispatch')
class ArticleUpdateView(UpdateView):
    model = Article
    form_class = ArticleForm
    template_name = 'blog/article_update_form.html'
    def get_object(self,queryset=None):
        obj = super().get_object(queryset=queryset)
        if obj.author != self.request.user:
            raise Http404
        return obj

@method_decorator(login_required, name='dispatch')
class ArticleDeleteView(DeleteView):
    model = Article
    success_url = reverse_lazy('blog:article_list')
    #DeleteView类试图默认需要模板： model_confirm_delete.html进行确认删除操作，通过重写DeleteView的get方法实现只需在前
    #端用javascript来实现一个pop-up来确认删除操作，例如：
    # <a href="javascript:if(confirm('确实要删除吗?'))location='{% url 'blog:article_delete' article.id article.slug %}'">删除</a>
    def get(self, request, *args, **kwargs):
        return self.delete(request, *args, **kwargs)
    '''
    template_name = 'blog/article_confirm_delete.html'
    success_url = reverse_lazy('blog:article_list')
    def get_object(self,queryset=None):
        obj = super().get_object(queryset=queryset)
        if obj.author != self.request.user:
            raise Http404
        return obj
    def post(self,*args,**kwargs):
        self.object = self.get_object()
        self.object.delete()
        data = {'success':'OK'}
        return JsonResponse(data)
    '''

@method_decorator(login_required,name='dispatch')
class PublishedArticleListView(ListView):
    template_name = "blog/published_article_list.html" #不指定模板的情况下，默认为：app_name/model_name_list.html
    paginate_by = 3
    def get_queryset(self):
        return Article.objects.filter(author=self.request.user).filter(status='p').order_by('-pub_date')

@method_decorator(login_required, name='dispatch')
class ArticleDraftListView(ListView):
    template_name = "blog/article_draft_list.html"
    paginate_by = 3
    def get_queryset(self):
        return Article.objects.filter(author=self.request.user).filter(status='d').order_by('-pub_date')


class CategoryListView(ListView):
    model = Category

'''查询属于某一类别的文章，我们可以使用Article.objects.filter()方法，这个方法查询的结果数据类型是QuerySet类型，而不是List类型。
当一个类别有子类别时，我们需要分别查询属于每个子类的文章数据集QuerySet，然后利用union方法把它们合并，最后通过分页显示。'''
class CategoryDetailView(DetailView):
    model = Category
    def get_context_data(self,**kwargs):
        context = super().get_context_data(**kwargs)
        if self.object.has_child():
            articles = Article.objects.filter()
            categorys = self.object.category_set.all()
            for category in categorys:
                queryset = Article.objects.filter(category=category.id).order_by('-pub_date')
                articles.union(queryset)
        else:
            articles = Article.objects.filter(category=self.object.id).order_by('-pub_date')
        paginator = Paginator(articles,3)
        page = self.request.GET.get('page')
        page_obj = paginator.get_page(page)
        context['page_obj'] = page_obj
        context['paginator'] = paginator
        context['is_paginated'] = True
        return context

class TagDetailView(DetailView):
    model = Tag
    def get_object(self,queryset=None):
        obj = super().get_object(queryset=queryset)
        return obj

logger = logging.getLogger(__name__)
@method_decorator(login_required,name='dispatch')
class ArticleCommentView(View):

    def post(self, request, *args, **kwargs):
        user = self.request.user
        text = self.request.POST.get('comment', '')
        if not request.session['is_login']:
            logger.error(
                '[CommentView]当前用户非活动用户：[{}]'.format(user.username)
            )
            request.session['LoginForm'] = request.META.get('HTTP_REFERER', '/')
            return render(request,'users/login.html')
        article_id = self.kwargs.get('pk', '')
        slug = self.kwargs.get('slug1','')
        article = Article.objects.get(id=article_id)

        #保存评论
        parent = None
        if text.startswith('@['):
            import ast
            parent_str = text[1:text.find(':')]
            parent_id = ast.literal_eval(parent_str)[1]
            text = text[text.find(':')+2:]
            try:
                parent = Comment.objects.get(pk=parent_id)
                info = '{}回复了你在 {} 的评论'.format(
                    user.username,
                    parent.article.title,
                )

            except Comment.DoesNotExist:
                logger.error(u'[CommentView]评论引用错误:%s' % parent_str)
                return HttpResponse('请勿修改评论代码！', status=403)

        if not text:
            logger.error('[CommentView]当前用户输入空评论：[{}]'.format(user.username))
            return HttpResponse('请输入评论内容！', status=403)
        comment = Comment.objects.create(
            user=user,
            article=article,
            text=text,
            parent=parent,
        )
        return HttpResponse(text)

        try:
            img = comment.user.image
        except Exception as e:
            img = "/media/default.png"


        print_comment = '<p>评论：{}</p>'.format(text)
        if parent:
            print_comment = '<div class=\"comment-quote\">\
                                <p>\
                                    <a>@{}</a>\
                                    {}\
                                </p>\
                            </div>'.format(
                                parent.user.username,
                                parent.text,
                            ) + print_comment

        # 返回当前评论
        html = "<li>\
                    <div class=\"comment-tx\">\
                        <img src={} width=\"40\"></img>\
                    </div>\
                    <div class=\"comment-content\">\
                        <a><h1>{}</h1></a>\
                        {}\
                        <p>{}</p>\
                    </div>\
                </li>".format(
                    img,
                    comment.user.username,
                    print_comment,
                    datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                )

        user.set_comment_num()
       # return redirect('article_detail', article.pk=article_id)
        return redirect(reverse('blog:article_detail',args=[str(article_id),slug]))


@login_required()
def article_publish(request,pk,slug1):
    article = get_object_or_404(Article,pk,slug1)
    article.published()
    return redirect(reverse('blog:article_detail',args=[str(pk),slug1]))

@login_required()
def article_search(request):
    tag=request.GET.get('q')
    articles = Article.objects.filter(tags=tag).order_by('-pub_date')
    paginator = Paginator(articles,3)
    page_obj = paginator.get_page('1')
    content= {'page_obj':page_obj,
              'paginator': paginator,
              'is_paginated':True,
              }
    return render(request,'blog/published_article_list.html',context=content)

def test(request):
    #article = Article.objects.all().first()
    if request.method == "GET":
        #testform = CategoryForm()
        testform = TagForm()
        return render(request,'blog/test.html',{'aform':testform})
    elif request.method == "POST":
        #testform = CategoryForm(request.POST)
        testform = TagForm(request.POST)
        if testform.is_valid():
            testform.save()
        return HttpResponse("保存成功")